Форум dkLab и Denwer
Здесь общаются Web-разработчики.
Генеральный спонсор:
Хостинг «Джино»

Проектирование простейшего (!) модуля для абстракции от SQL-сервера. (Дмитрий Котеров)
Goto page 1, 2  Next
Author Message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Mon Jun 13, 2005 2:17 pm (написано за 3 минуты 6 секунд)
   Post subject: Проектирование простейшего (!) модуля для абстракции от SQL-сервера.
Reply with quote

В последнее время моя практика показывает, что в подавляющем большинстве случаев для работы с SQL-сервером достаточно написать и использовать примерно следующие функции:

select - выполнение SELECT-запроса и возврат всех строк результата.
selectRow - то же самое, но возвращает только первую строку
selectCol - то же самое, но возвращает весь первый столбец в виде списка
selectCell - то же самое, но возвращает первую ячейку первой строки
query - для выполнения не-select запросов; для insert - выдает mysql_insert_id() (на самом деле, это же должен и select делать, так что select - синоним для query).

У всех этих функций параметры одинаковые: function($query, arg1, arg2, ...), где argN - это аргументы для placeholder-ов (Сходите, пожалуйста, в Поиск по запросу «placeholder». Спасибо!). В большинстве проектов слой абстракции, разделяющий выполнение запроса и получение результата, не требуется, ибо нужны все результирующие данные, а ограничения идут через LIMIT.

Можно еще ввести абстрагирование от LIMIT (в разных БД по-разному он записывается; например, в FireBird - "SELECT FIRST x SKIP y"), например:
Code (php): скопировать код в буфер обмена
// Получение всех записей (первый параметр - НЕ ЧИСЛО, т.е. !is_numeric()).
$rows = select('SELECT * FROM A WHERE i>?', 10);
// Получение 20 записей, начиная с 10-й. Общее число записей сохраняется в $total.
// Фактически, может разворачиваться в 2 запроса: один - с COUNT-ом (для вычисления $total),
// второй - с LIMIT-ом (для ограничения).
$rows = select(10, 20, $total, 'SELECT * FROM A WHERE i>?', 10);
Да, все эти функции, конечно, разумно сделать в виде методов некоторого класса - чтобы можно было легко менять БД потом или же использовать несколько подключений.

Кроме того, если в выборке SELECT-а присутствует столбец с определенным фиксированным именем (например, 'ARRAY_KEY'), то значение этого столбца используется как ключ в результирующем массиве. Если же такого столбца нет, то возвращается просто список.

Суть в том, что с применением описанного подхода код, похоже, становится максимально лаконичным, не теряя в то же время универсальности, и не обрезая возможностей SQL-сервера.

Кто что думает на эту тему?
Back to top
View user's profile Send private message Send e-mail
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Mon Jun 13, 2005 11:34 pm (спустя 9 часов 16 минут; написано за 2 минуты 32 секунды)
   Post subject:
Reply with quote

Дмитрий Котеров
Да, пожалуй это просто идеальное решение :)). Немного напрягает твоё желание сделать всё независимым от БД... ИМХО это как раз не очень-то и часто требуется... Вот только насчёт selectCol не очень понятно - зачем это нужно?
Back to top
View user's profile Send private message Send e-mail
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Tue Jun 14, 2005 12:04 am (спустя 30 минут; написано за 1 минуту 13 секунд)
   Post subject:
Reply with quote

Ну, иногда бывает нужно выбрать ровно один столбец - особенно в DISTINCT-запросах. Ну а совместно с ARRAY_KEY можно через selectCol() получать даже справочники вида ключ=>значение (через select() получим в виде ключ=>array(поле=>значение)).
Back to top
View user's profile Send private message Send e-mail
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Tue Jun 14, 2005 7:37 pm (спустя 19 часов 32 минуты; написано за 12 секунд)
   Post subject:
Reply with quote

Дмитрий Котеров
Ясно. В любом случае, идея очень неплохая
Back to top
View user's profile Send private message Send e-mail
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Wed Jun 15, 2005 3:20 pm (спустя 19 часов 42 минуты; написано за 2 минуты 59 секунд)
   Post subject:
Reply with quote

Начал делать. Уже почти доделал, на самом деле, модуль для FireBird, - только не тестировал еще. Правда, "слишком простой" данную библиотеку назвать уже нельзя, однако простым остается ее использование. Сложности касаются, в основном, работы с блобами в десятки мегабайтов (в FireBird и PostgreSQL своя специфика для этого, в MySQL ее нет).

Основные поддерживаемые возможности:
- транзакции
- абстрагирование от COUNT(*), FIRST x SKIP y
- абстрагирование от типа БД
- логирование запросов
- работа с блобами как с объектами
- placeholder-ы с поддержкой списковых значений (для IN-выражений)

Через 2 недели примерно, когда доделаем проект с ее использованием, начну потихоньку выкладывать.
Back to top
View user's profile Send private message Send e-mail
Евгений Бондарев
Модератор



Joined: 10 Mar 2003
Posts: 723
Карма: 16
   поощрить/наказать

Location: Харьков/Киев, Украина

PostPosted: Thu Jun 16, 2005 8:21 am (спустя 17 часов 1 минуту; написано за 52 секунды)
   Post subject:
Reply with quote

Дмитрий, а почему Вы упорно неприемлите существующие классы абстракций типа ADODB и PEAR::DB?
Там все это есть..
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Thu Jun 16, 2005 11:33 am (спустя 3 часа 12 минут; написано за 1 минуту 28 секунд)
   Post subject:
Reply with quote

Нет, как раз этого всего там и нет. Там, считайте, обертка над стандартным seek-ориентированным интерфейсом PHP, крайне многословным и неуклюжим в реальных приложениях. Ну а уж интерфейс placeholder-ов в PEAR вообще заслуживет отдельных проклятий.
Back to top
View user's profile Send private message Send e-mail
Иван Шумков
Участник форума



Joined: 30 Dec 2004
Posts: 229
Карма: 6
   поощрить/наказать

Location: Россия, Санкт-Петербург

PostPosted: Thu Jun 23, 2005 6:44 pm (спустя 7 дней 7 часов 10 минут; написано за 1 минуту 51 секунду)
   Post subject:
Reply with quote

А можно полюбопытствовать. Очень интересно.

Сам хотел нечто подобное иметь. Урезал AdoDB, благо там есть туториал по урезаню, но результатом не доволен. Лучше уж с нуля написать.
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Thu Jun 23, 2005 10:28 pm (спустя 3 часа 44 минуты; написано за 1 минуту 46 секунд)
   Post subject:
Reply with quote

А что тут любопытствовать... Ждите наблу соответствующую. Думаю, код сюда выложу еще раньше.
Кстати, сразу скажу, что будет штатно 2 класса: Ibase и Mysql, потому что следующие 2 проекта у нас как раз на этих БД.

Сейчас осталось продумать единый интерфейс поддержки ошибок. Исключения делать нельзя, к сожалению - нужна совместимость с PHP4. А жаль.
Back to top
View user's profile Send private message Send e-mail
Иван Шумков
Участник форума



Joined: 30 Dec 2004
Posts: 229
Карма: 6
   поощрить/наказать

Location: Россия, Санкт-Петербург

PostPosted: Thu Jun 23, 2005 10:36 pm (спустя 7 минут; написано за 1 минуту 17 секунд)
   Post subject:
Reply with quote

Дмитрий Котеров

Простите, "интерфейс поддержки ошибок" на PHP4, отличается от PHP5?
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Fri Jun 24, 2005 10:00 am (спустя 11 часов 24 минуты; написано за 58 секунд)
   Post subject:
Reply with quote

Еще раз: в PHP5 существует поддержка исключений (инструкция throw), и обработку ошибок нужно делать, конечно же, через исключения. Это правильно, это компактно, красиво и универсально. Однако в PHP4 никаких исключений нет. Поэтому в целях совместимости - придется обойтись без исключений.
Back to top
View user's profile Send private message Send e-mail
Иван Шумков
Участник форума



Joined: 30 Dec 2004
Posts: 229
Карма: 6
   поощрить/наказать

Location: Россия, Санкт-Петербург

PostPosted: Fri Jun 24, 2005 3:07 pm (спустя 5 часов 6 минут; написано за 35 секунд)
   Post subject:
Reply with quote

Дмитрий Котеров
Спасибо большое. Видимо надо преобрести вашу книгу по PHP5.
Back to top
View user's profile Send private message
Иван Шумков
Участник форума



Joined: 30 Dec 2004
Posts: 229
Карма: 6
   поощрить/наказать

Location: Россия, Санкт-Петербург

PostPosted: Tue Jun 28, 2005 4:28 am (спустя 3 дня 13 часов 20 минут; написано за 36 секунд)
   Post subject:
Reply with quote

Дмитрий Котеров
Вы имели ввиду exceptions (ru3.php.net/exceptions)?
Back to top
View user's profile Send private message
Сабаев Александр
Заглянувший



Joined: 12 Feb 2005
Posts: 3
Карма: 0
   поощрить/наказать


PostPosted: Wed Jun 29, 2005 7:05 am (спустя 1 день 2 часа 37 минут; написано за 2 минуты 2 секунды)
   Post subject: Обратите внимание на PDO
Reply with quote

Я бы сказал что это подобие перлового DBI - независимость от типа базы без потери гибкости
Правда он только в 5.1
Back to top
View user's profile Send private message
АндрейВВ
Заглянувший



Joined: 13 Jul 2005
Posts: 4
Карма: 0
   поощрить/наказать

Location: СПб

PostPosted: Thu Jul 14, 2005 4:16 pm (спустя 15 дней 9 часов 11 минут; написано за 1 секунду)
   Post subject:
Reply with quote

Моя практика показывает тоже самое. А именно написание вышеупомянутых функций.
Я лично около 2 лет назад написал класс по работе с БД.
Так вот туда еще дополнительно вошли следующие вещи: обработка ошибок (сигнализация их), выбор типа БД (в моем случае MySQL и MsSQL),
ну и преобразование в XML ответ (для варианта MySQL) по типу как это сделано в MsSQL (for XML auto).

Результат: юзаю данную тему много времени и не думаю ни о чем. Все быстро и удобно.

Поэтому мой личный респект Дмитрию Кóтерову
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Thu Jul 14, 2005 4:41 pm (спустя 24 минуты)
   Post subject:
Reply with quote

Для MySQL уже все готово и используется (включая обработку ошибок). До ibase - пока еще так и не добрался. Как только будет проект, работающий на этой штуке, сразу же выложу библиотеку.

Планируется еще вот что сделать: "умную" поддержку "собак". Т.е. если мы пишем:

$DB->select("ошибочный запрос");

то вызывается ассоциированный обработчик ошибок (рекомендованное действие - завершение скрипта и выдача отладочной информации по месту выполнения запроса; для PHP5 он может также генерировать обычное исключение). А если же пишем:

@$DB->select("ошибочный запрос");

то - обработчик ошибки НЕ вызывается, однако error_reporting также не снижается внутри функции до 0 (вручную переставляется назад), что позволяет перехватывать разного рода ошибки в библиотеке. Последнюю ошибку в этом случае можно получить по $DB->error.

Т.е. в данном применении @ используется точно так же, как try...catch констркуция. И это позволяет обойтись без исключений, сохранив их удобства, в PHP4.
Back to top
View user's profile Send private message Send e-mail
Guest






Карма: 388
   поощрить/наказать


PostPosted: Sat Jul 16, 2005 12:25 pm (спустя 1 день 19 часов 44 минуты; написано за 1 минуту 28 секунд)
   Post subject:
Reply with quote

Quote:
Для MySQL уже все готово и используется (включая обработку ошибок). До ibase - пока еще так и не добрался. Как только будет проект, работающий на этой штуке, сразу же выложу библиотеку.
Эээ... Понимаю, что торопить нехорошо, но можно все-таки только для MySQL? ibase редко кто использует. Или хотя бы пример кода с "умной" поддержкой "собак", так что не врубаюсь...
Back to top
Константин Жинько [tIT]
Сотрудник «Лаборатории»



Joined: 12 Jun 2004
Posts: 2264
Карма: 106
   поощрить/наказать

Location: Москва

PostPosted: Mon Jul 18, 2005 6:29 pm (спустя 2 дня 6 часов 4 минуты; написано за 3 минуты 49 секунд)
   Post subject:
Reply with quote

Дмитрий Котеров wrote:
Ну, иногда бывает нужно выбрать ровно один столбец
Не иногда, а очень часто =))
По крайней мере, в моей практике (-;
Дмитрий Котеров wrote:
Поэтому в целях совместимости - придется обойтись без исключений.
Сколько кода придется переконопатить! Мне-то ни к чему четверка. Я за максимальный комфорт =)
Упорно жду, когда выйдет релиз 5.1, чтобы поставить на наши сервера.
Сабаев Александр wrote:
Я бы сказал что это подобие перлового DBI
А Вы сами с PDO работали?
Может, поделитесь впечатлениями, дабы не читать доки "натощак"? *)
Гость wrote:
но можно все-таки только для MySQL?
Зачем "только"?
Гость wrote:
ibase редко кто использует
Раньше может и редко, а сейчас пакет расширения есть к Денверу (-;
Back to top
View user's profile Send private message
dacuan
Участник форума



Joined: 16 Mar 2005
Posts: 20
Карма: 0
   поощрить/наказать


PostPosted: Sat Jul 23, 2005 10:15 am (спустя 4 дня 15 часов 46 минут; написано за 11 минут 1 секунду)
   Post subject:
Reply with quote

А если пойти не таким путем. Введем некоторой SQL-подобный язык, и, во время компиляции запроса транслируем его в SQL-запрос используемого сервера БД. Наличие транслятора позволит полностью абстрагироваться от сервера и синтаксиса его запросов.

В результате код
Code (php): скопировать код в буфер обмена
//
$rows = select(10, 20, $total, 'SELECT * FROM A WHERE i>?', 10);
Будет выглядеть, например так (учитывая что всю работу с БД предполагается обернуть в класс):
Code (php): скопировать код в буфер обмена
$rows = $db->select('SELECT COUNT_TOTAL * FROM A WHERE i>? LIMIT 10,20', 10);
$total = $db->get_total();
Или даже так:
Code (php): скопировать код в буфер обмена
$res = $db->query('SELECT COUNT_TOTAL * FROM A WHERE i>? LIMIT 10,20', 10);
$rows = $db->get_rows();
$total = $db->get_total();
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Sat Jul 23, 2005 11:55 am (спустя 1 час 39 минут; написано за 2 минуты 21 секунду)
   Post subject:
Reply with quote

Штука в том, что далеко не во всех запросах бывает нужно считать общее число записей, подпадающих под условие. Все-таки это довольно дорогая операция (дополнительнгый SQL-запрос с COUNT). А следовательно, в Вашей схеме возможен только один выход: делать дополнительный COUNT-запрос не в query(), а в get_total(). А это идеологически довольно кривовато.

К тому же на практике гораздо удобнее объединять query() и get_rows() (см. выше примеры), так что Ваш код избыточен.
Back to top
View user's profile Send private message Send e-mail
dacuan
Участник форума



Joined: 16 Mar 2005
Posts: 20
Карма: 0
   поощрить/наказать


PostPosted: Sat Jul 23, 2005 1:24 pm (спустя 1 час 28 минут; написано за 13 минут 33 секунды)
   Post subject:
Reply with quote

Дмитрий Котеров wrote:
Штука в том, что далеко не во всех запросах бывает нужно считать общее число записей, подпадающих под условие. Все-таки это довольно дорогая операция (дополнительнгый SQL-запрос с COUNT). А следовательно, в Вашей схеме возможен только один выход: делать дополнительный COUNT-запрос не в query(), а в get_total(). А это идеологически довольно кривовато.
Запрос без COUNT будет выглядеть так:
Code (php): скопировать код в буфер обмена
$rows = $db->select('SELECT * FROM A WHERE i>? LIMIT 10,20', 10);
То есть COUNT_TOTAL, это некий указатель, что необходимо подсчитывать общее количество записей. Если его нет, то второй запрос производится не будет. Это чем-то напоминает использование SELECT DISTINCT в MySQL. В принципе, таких "опций" может быть несколько, включая тот же DISTINCT.
Дмитрий Котеров wrote:
К тому же на практике гораздо удобнее объединять query() и get_rows() (см. выше примеры), так что Ваш код избыточен.
С этим согласен, но такая избыточность связана с методом обработки ошибок. В Вашем случае метод select() возвращает либо массив либо false в случае, если произошла ошибка (может и не так, но вопрос о выбранном методе обработки ошибок в ветке раскрыт не был). В таком случае вызов будет выглядеть примерно так:
Code (php): скопировать код в буфер обмена
if (false === ($rows = select(10, 20, $total, 'SELECT * FROM A WHERE i>?', 10)) {
    die (www.php.net/die)('Error');
}
Что несколько громоздко. В моем случае select() всегда возвращает логический тип. Да и конструкция "or die()", при использовании Вашего подхода будет срабатывать, если вернется пустой массив.

Кроме того, если делать получение общего числа записей предложенным мной способом, то доступ к записям через get_rows() будет "идеалогически выдержанным" ;) -- один вызов для выполнения запроса, причем форма вызова не меняется от того, хотим ли мы делать подсчет общего числа записей или нет, и по отдельному вызову на получения общего числа и рядов.
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Mon Jul 25, 2005 12:19 pm (спустя 1 день 22 часа 55 минут; написано за 1 минуту 33 секунды)
   Post subject:
Reply with quote

Все-таки мне не нравится COUNT_TOTAL, ох не нравится... Не на том слое абстракции идет обработка данных. Что касается поведения select() в случае ошибки, то, если он вызван без @, поведение такое: работа скрипта завершается, печатается отладочное сообщение (в логи или в браузер). Ну а уж если есть @, тогда - ошибки нет, но ее код и текст можно получить из $DB->error.
Back to top
View user's profile Send private message Send e-mail
dacuan
Участник форума



Joined: 16 Mar 2005
Posts: 20
Карма: 0
   поощрить/наказать


PostPosted: Mon Jul 25, 2005 12:51 pm (спустя 31 минуту; написано за 12 минут 25 секунд)
   Post subject:
Reply with quote

Дмитрий Котеров wrote:
Все-таки мне не нравится COUNT_TOTAL, ох не нравится... Не на том слое абстракции идет обработка данных. Что касается поведения select() в случае ошибки, то, если он вызван без @, поведение такое: работа скрипта завершается, печатается отладочное сообщение (в логи или в браузер). Ну а уж если есть @, тогда - ошибки нет, но ее код и текст можно получить из $DB->error.
То есть, если я хочу прикрутить свой обработчик ошибок, то вызов select() будет выглядеть примерно так:
Code (php): скопировать код в буфер обмена
if (!$rows = @$db->select(10, 20, $total, 'SELECT * FROM A WHERE i>?', 10)) {
    if ($db->error) {
        //
    }   
}
или так
Code (php): скопировать код в буфер обмена
if ((!$rows = @$db->select(10, 20, $total, 'SELECT * FROM A WHERE i>?', 10)) && $db->error) {
        // Обработка ошибки
}
Код теряет лаконичность.
А если необходимо применить лимиты, но не считать общее число записей. Например, на главной странице электронного магазина выводим три случайных товара. Как в этом случае должен вызываться метод select()? Можно в $total передавать -1, NULL или какой-либо другой флаг, или же обрабатывать еще один тип вызова метода:
Code (php): скопировать код в буфер обмена
$rows = $db->select(10, 20, 'SELECT * FROM A WHERE i>?', 10);
IMHO перегрузка вызовов методов не есть хорошо. Она вносит путаницу в код. Странно и то, что лимиты выделены из всех параметров запроса в отдельную группу, хотя, если утрировать, с тем же успехом можно вынести в отдельные аргументы условия группировки и фильтрации.
В модели, описанной мною выше, нечеткость вызова select() исчезает за счет усложнения обработки переданного шаблона и некоторой (спорной) избыточности кода.
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Mon Jul 25, 2005 1:16 pm (спустя 24 минуты; написано за 4 минуты 35 секунд)
   Post subject:
Reply with quote

dacuan wrote:
А если необходимо применить лимиты, но не считать общее число записей.
function select($query)
function selectLimited($from, $num, $query)
function selectPage($from, $num, &$total, $query)
dacuan wrote:
if (!$rows = @$db->select(10, 20, $total, 'SELECT * FROM A WHERE i>?', 10)) {
Нет,
if (null !== ($rows = @$db->select(10, 20, $total, 'SELECT * FROM A WHERE i>?', 10)))

Но, кстати, необходимость кастомной обработки ошибок возникает крайне редко. В подавляющем большинстве случаев самое востребованное действие - завершение работы и выдача подробной отладочной информации.
dacuan wrote:
Странно и то, что лимиты выделены из всех параметров запроса в отдельную группу, хотя, если утрировать, с тем же успехом можно вынести в отдельные аргументы условия группировки и фильтрации.
Я тут подумал немного... Возможно, я все-таки соглашусь с Вами насчет COUNT_TOTAL.

Давайте обсудим, что делать с LIMIT-ом. К сожалению, у разных SQL-серверов разный синтаксис: MySQL использует суффикс "LIMIT X,Y", а FireBird - префикс "SELECT FIRST X SKIP Y". В принципе, можно это дело обрабатывать, преобразуя запросы одного вида в другой (как в стандарте SQL 99 с ограничением? вроде бы как раз FIRST X SKIP Y - стандарт?).
Back to top
View user's profile Send private message Send e-mail
dacuan
Участник форума



Joined: 16 Mar 2005
Posts: 20
Карма: 0
   поощрить/наказать


PostPosted: Mon Jul 25, 2005 2:51 pm (спустя 1 час 35 минут; написано за 17 минут 5 секунд)
   Post subject:
Reply with quote

Дмитрий Котеров wrote:
 К сожалению, у разных SQL-серверов разный синтаксис: MySQL использует суффикс "LIMIT X,Y", а FireBird - префикс "SELECT FIRST X SKIP Y". В принципе, можно это дело обрабатывать, преобразуя запросы одного вида в другой (как в стандарте SQL 99 с ограничением? вроде бы как раз FIRST X SKIP Y - стандарт?).
Грустно осознавать, но в стандарте SQL-99 я не силен :(. Но главную проблему я вижу не в этом. Если синтаксис ограничения выборки рядов из полученного множества одинаков для различных СУБД, что-нибудь вроде
Code (any language): скопировать код в буфер обмена
<keyword 1> <First row> <keyword 2> <Number of rows>
то его трансляция не составит большого труда. Даже если синтаксис изменится до такого:
Code (any language): скопировать код в буфер обмена
<keyword 1> <First row> <keyword 2> <Last row>
то и в этом случае трансляцию можно будет легко произвести.
Основная проблема в другом. В идеале, транслятор должен полностью переводить запрос в его логическое представление. Он должен понимать все функции (CONCAT(), NOW(), DATE_FORMAT()), методы сравнивания полей (=, <> , <=, >=), способы связывания таблиц (LEFT JOIN, INNER JOIN, RIGHT JOIN, ",") и транслировать логическую структуру запроса в SQL-диалект, используетмый СУБД. В результате получится продукт, по сложности сопоставимый с SQL-парсеров базы данных, но написанный на PHP.
Поэтому необходимо где-то "провести черту" и возложить на скрипт только базовый разбор, без анализа синтаксиса вызова функций и т.п. Но есть риск потерять в переносимость конечного приложения.
А вот как проводить черту и что выполнять на стороне PHP я пока не придумал.
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Mon Jul 25, 2005 3:20 pm (спустя 28 минут; написано за 20 секунд)
   Post subject:
Reply with quote

Черта - это как раз и есть LIMIT. Дальше LIMIT-а, я думаю, смысла "ковырять" SQL-диалект нет.
Back to top
View user's profile Send private message Send e-mail
dacuan
Участник форума



Joined: 16 Mar 2005
Posts: 20
Карма: 0
   поощрить/наказать


PostPosted: Mon Jul 25, 2005 3:57 pm (спустя 37 минут; написано за 4 минуты 46 секунд)
   Post subject:
Reply with quote

Дмитрий Котеров wrote:
Черта - это как раз и есть LIMIT. Дальше LIMIT-а, я думаю, смысла "ковырять" SQL-диалект нет.
Возможно Вы правы, но даже использование псевдонимов (AS) мною часто используемое, в MS Acess имеет другой синтаксис. Подозреваю, что в других СУБД тоже найдутся подобные отличия.
Например, может отсутствовать объединение таблиц через "," и вместо него используется "INNER JOIN ON". И приложение, использующее класс абстракции не будет работать на этой базе данных.
Back to top
View user's profile Send private message
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Mon Jul 25, 2005 6:40 pm (спустя 2 часа 42 минуты; написано за 1 минуту 12 секунд)
   Post subject:
Reply with quote

Данный класс не преследует задачу ПОЛНОГО абстрагирования от СУБД и выравнивания диалектов. Потому-то изначально и были сделаны 3 функции для различных вариантов limit-а. У него другая задача - максимально упростить написание скриптов с его использованием.
Back to top
View user's profile Send private message Send e-mail
dima.exe
Guest





Карма: 388
   поощрить/наказать


PostPosted: Tue Jul 26, 2005 12:42 am (спустя 6 часов 2 минуты; написано за 38 секунд)
   Post subject:
Reply with quote

Вот еще один вариант решения этой проблеммы, по моему мнению очень удачный
propel.phpdb.org/docs/user_guide/chapters/FindingObjects.html#FindingRecods.Criteria
Back to top
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Tue Jul 26, 2005 10:01 am (спустя 9 часов 19 минут; написано за 2 минуты 16 секунд)
   Post subject:
Reply with quote

dima.exe, это совсем не то. И цели propel приследует совершенно другие.

dacuan, все-таки насчет COUNT_TOTAL я еще немного подумал, и решил не делать. И вот почему: данная библиотека - это, как я уже говорил, не средство "выравнивания диалектов", а средство более удобного и простого обращения к SQL-серверу. Соответственно, кода для "выравнивания диалектов" в ней изначально нет и не планировалось. Поддержка COUNT_TOTAL была бы первым блоком кода такого рода, то есть - создает прецедент, причем прецедент поведения, которое в библиотеке не закладывалось изначально. По сему - быть трем функциям.
Back to top
View user's profile Send private message Send e-mail
dacuan
Участник форума



Joined: 16 Mar 2005
Posts: 20
Карма: 0
   поощрить/наказать


PostPosted: Tue Jul 26, 2005 10:57 am (спустя 55 минут; написано за 1 минуту 4 секунды)
   Post subject:
Reply with quote

Дмитрий Котеров wrote:
все-таки насчет COUNT_TOTAL я еще немного подумал, и решил не делать. И вот почему: данная библиотека - это, как я уже говорил, не средство "выравнивания диалектов", а средство более удобного и простого обращения к SQL-серверу. Соответственно, кода для "выравнивания диалектов" в ней изначально нет и не планировалось. Поддержка COUNT_TOTAL была бы первым блоком кода такого рода, то есть - создает прецедент, причем прецедент поведения, которое в библиотеке не закладывалось изначально. По сему - быть трем функциям.
Ваше право :) Но я надеюсь выкроить время, чтобы решить проблему COUNT_TOTAL. Будут положительные результаты, отпишу сюда.
Back to top
View user's profile Send private message
dima.exe
Guest





Карма: 388
   поощрить/наказать


PostPosted: Tue Jul 26, 2005 7:17 pm (спустя 8 часов 20 минут; написано за 4 минуты 38 секунд)
   Post subject:
Reply with quote

Дмитрий Котеров wrote:
dima.exe, это совсем не то. И цели propel приследует совершенно другие.
Я не про Propel,
а про класс Criteria который в нем используется,достаточно удобная и высокоуровневая обертка над SQL которая может использоватся в большинстве запросов.
Back to top
dacuan
Участник форума



Joined: 16 Mar 2005
Posts: 20
Карма: 0
   поощрить/наказать


PostPosted: Wed Jul 27, 2005 11:10 am (спустя 15 часов 53 минуты; написано за 3 минуты 15 секунд)
   Post subject:
Reply with quote

dima.exe
Об удобстве Criteria можно поспорить. Сравни код
Code (php): скопировать код в буфер обмена
$c = new Criteria();
$c->add(AuthorPeer::FIRST_NAME, "Leo%", Criteria::LIKE);
$c->add(AuthorPeer::FIRST_NAME, "Leonardo", Criteria::NOT_EQUAL);
$results = AuthorPeer::doSelect($c);
с таким
Code (php): скопировать код в буфер обмена
$rows = $db->select('SELECT * FROM Authors WHERE first_name LIKE ? AND first_name = ?', 'Leo%', 'Leonardo');
На мой взгляд второй вариант нагляднее и проще. По крайней мере видно ЧТО происходит на самом деле.
А если условий больше?
Back to top
View user's profile Send private message
dima.exe
Guest





Карма: 388
   поощрить/наказать


PostPosted: Wed Jul 27, 2005 2:20 pm (спустя 3 часа 9 минут; написано за 6 минут 21 секунду)
   Post subject:
Reply with quote

dacuan wrote:
dima.exe
Об удобстве Criteria можно поспорить. Сравни код
Code (php): скопировать код в буфер обмена
$c = new Criteria();
$c->add(AuthorPeer::FIRST_NAME, "Leo%", Criteria::LIKE);
$c->add(AuthorPeer::FIRST_NAME, "Leonardo", Criteria::NOT_EQUAL);
$results = AuthorPeer::doSelect($c);
с таким
Code (php): скопировать код в буфер обмена
$rows = $db->select('SELECT * FROM Authors WHERE first_name LIKE ? AND first_name = ?', 'Leo%', 'Leonardo');
На мой взгляд второй вариант нагляднее и проще. По крайней мере видно ЧТО происходит на самом деле.
А если условий больше?
Вариант с Criteria тоже достаточно простой, просто не превычный систаксис запроса.
Подход который реализует Criteria позволяет полностью абстрагироватся от SQL на не сложных запросах (а их большинство), в этом ее большой плюс.
Back to top
Юрий Насретдинов
Модератор



Joined: 13 Mar 2003
Posts: 8642
Карма: 198
   поощрить/наказать

Location: 007 495

PostPosted: Wed Jul 27, 2005 2:51 pm (спустя 30 минут; написано за 36 секунд)
   Post subject:
Reply with quote

dima.exe wrote:
в этом ее большой плюс.
Хм, это утверждение в корне неверно. SQL - очень удобный и наглядный язык для запросов, и абстрагироваться от него, заменяя его на 4! вызова функций, просто глупо.
Back to top
View user's profile Send private message Send e-mail
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Wed Jul 27, 2005 3:41 pm (спустя 50 минут; написано за 26 секунд)
   Post subject:
Reply with quote

Ничего их не большинство. Как раз при грамотном использовании базы почти в каждом запросе встречается JOIN.
Back to top
View user's profile Send private message Send e-mail
Юрий Лисицкий
Guest





Карма: 388
   поощрить/наказать


PostPosted: Thu Aug 11, 2005 4:11 pm (спустя 15 дней 29 минут; написано за 3 минуты 41 секунду)
   Post subject:
Reply with quote

Дмитрий Котеров wrote:
Ну а уж интерфейс placeholder-ов в PEAR вообще заслуживет отдельных проклятий.
Что конкретно в механизме плейсхолдеров не так. Спрашиваю потому, что некоторое время пользовалься этой возможностью из PEAR::DB и каких-то проблем не заметил. Многословно - это да. Сейчас есть задача на довольно большое веб-приложение и хотелось-бы услышать мнение авторитетного человека чтобы заранее предостеречь себя от возможных проблем. Спасибо.
Back to top
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Thu Aug 11, 2005 4:29 pm (спустя 18 минут; написано за 13 секунд)
   Post subject:
Reply with quote

Главный недостаток - да, многословность.
Back to top
View user's profile Send private message Send e-mail
Guest






Карма: 388
   поощрить/наказать


PostPosted: Thu Aug 11, 2005 5:08 pm (спустя 38 минут; написано за 4 минуты 9 секунд)
   Post subject:
Reply with quote

Дмитрий Котеров
Согласен.

Еще вопрос. Может кто обащал внимание на творчество товарища Тони Марстона www.tonymarston.net/php-mysq и его Development Infrastructure for PHP www.tonymarston.net/php-mysql/infrastructure.html? Если, да, то каково мнение об єтом фреймворке? Мне кажется там довольно ынтересно реализован класс доступа к БД (с валидацией данных и прочими штуками). Сори, если это офтоп.
Back to top
Дмитрий Котеров
Администратор



Joined: 10 Mar 2003
Posts: 13665
Карма: 413
   поощрить/наказать


PostPosted: Fri Aug 12, 2005 10:07 am (спустя 16 часов 59 минут; написано за 1 минуту)
   Post subject:
Reply with quote

Гость, судя по всему, там что-то типа object-relational mapping. По крайней мере, SQL-запросов нигде нет в явном виде. Здесь же речь идет исключительно о классах для работы с SQL, без ограничения функциональности последнего. Так что - оффтопик.
Back to top
View user's profile Send private message Send e-mail
Display posts from previous:   
Post new topic   This topic is locked: you cannot edit posts or make replies. All times are GMT + 3 Hours
Goto page 1, 2  Next
Page 1 of 2    Email to a Friend.
You cannot post new topics in this forum. You cannot reply to topics in this forum. You cannot edit your posts in this forum. You cannot delete your posts in this forum. You cannot vote in polls in this forum. You cannot attach files in this forum. You can download files in this forum.
XML